<template>
  <div style="width: 100%">
    <div v-if="!isInput" class="text-desensitize-container">
      <!-- 数据展示 -->
      <div class="text-box">{{ text }}</div>
      <!-- 脱敏状态切换按钮 -->
      <div v-if="needEye" class="icon-box" @click="changeSecretState">
        <el-icon v-if="isEyeClose">
          <Hide/>
        </el-icon>
        <el-icon v-else>
          <View/>
        </el-icon>
      </div>
    </div>
    <!-- 输入框模式 -->
    <!-- 要编辑时，要选用v-model绑定数据 -->
    <div v-else class="input-container">
      <!-- 脱敏状态下的只读输入框 -->
      <el-input
          v-if="isEyeClose"
          v-bind="otherAttr"
          ref="inputA"
          :value="desensitizedText"
          :readonly="true"
          :placeholder="placeholder"
          @click="changeSecretState"
      >
        <template #suffix>
          <div v-if="needEye" class="icon-box" @click="changeSecretState">
            <el-icon>
              <Hide/>
            </el-icon>
          </div>
        </template>
      </el-input>

      <!-- 非脱敏状态下的可编辑输入框 -->
      <el-input
          v-else
          v-bind="otherAttr"
          ref="inputB"
          v-model="editValue"
          @input="changeValue"
          :readonly="!editable"
          :placeholder="placeholder"
      >
        <template #suffix>
          <div v-if="needEye" class="icon-box" @click="changeSecretState">
            <el-icon>
              <View/>
            </el-icon>
          </div>
        </template>
      </el-input>
    </div>
  </div>
</template>

<script>
import {Hide, View} from "@element-plus/icons-vue";

export default {
  name: 'text-desensitize',
  components: {View, Hide},
  props: {
    // 源数据
    modelValue: {
      type: String,
      default: ''
    },
    // 脱敏类型：idCard 证件号、phone 手机号等，根据定义的脱敏工具类中的类型
    type: {
      type: String,
      default: 'auto',
      validator: (val) => {
        const typeList = ['idCard', 'phone', 'name', 'auto']
        return typeList.includes(val)
      }
    },
    // 是否以input标签包裹
    isInput: {
      type: Boolean,
      default: false
    },
    // 是否可编辑
    editable: {
      type: Boolean,
      default: false
    },
    placeholder: {
      type: String,
      default: ''
    },
    otherAttr: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
      // 当前是否展示脱敏数据
      isEyeClose: true,
      desensitizedText: this.desensitizeTextFn(this.modelValue, this.type),
      editValue: this.modelValue
    }
  },
  watch: {
    // 监控 modelValue 改变
    modelValue: {
      handler(newVal) {
        this.editValue = newVal;
        this.desensitizedText = this.desensitizeTextFn(newVal, this.type);
      },
      immediate: true
    },
    // 监控 type 改变
    type: {
      handler(newVal) {
        this.desensitizedText = this.desensitizeTextFn(this.modelValue, newVal);
      }
    }
  },
  computed: {
    // 是否需要眼睛按钮
    needEye() {
      return this.modelValue && !this.modelValue.includes('***')
    },
    // 展示的数据
    text() {
      if (this.isEyeClose) {
        return this.desensitizedText
      }
      return this.editValue || ''
    }
  },
  methods: {
    changeValue(event) {
      const value = typeof event === 'string' ? event : event.target.value;
      this.editValue = value;
      this.desensitizedText = this.desensitizeTextFn(value, this.type)
      this.$nextTick(() => {
        this.$emit('update:modelValue', value)
      })
    },
    // 切换当前脱敏状态
    changeSecretState() {
      this.isEyeClose = !this.isEyeClose
      this.focusInput()
      let emitData = {
        text: this.editValue,
        desensitizedText: this.desensitizedText,
        show: !this.isEyeClose
      }
      this.$emit('secretStatusChange', emitData)
    },
    focusInput() {
      // 根据当前状态聚焦到对应的输入框
      this.$nextTick(() => {
        if (this.isEyeClose && this.$refs.inputA) {
          this.$refs.inputA.focus()
        } else if (!this.isEyeClose && this.$refs.inputB) {
          this.$refs.inputB.focus()
        }
      })
    },
    /**
     * 数据脱敏工具函数
     * @param value 需要脱敏的原始数据
     * @param type 脱敏类型
     * @returns 脱敏后的数据
     */
    desensitizeTextFn(value, type) {
      if (!value) return '';
      switch (type) {
        case 'idCard':
          if (value && value.length >= 18) {
            return value.substring(0, 6) + '********' + value.substring(14)
          } else if (value && value.length >= 4) {
            // 对于不完整的身份证号，简单处理
            return value.substring(0, 2) + '****' + value.substring(value.length - 2)
          } else return value;
        case 'phone':
          if (value && value.length === 11) {
            return value.substring(0, 3) + '****' + value.substring(7)
          } else if (value && value.length >= 2) {
            // 对于非标准长度的号码，保留前1位和后1位
            return value.charAt(0) + '****' + value.charAt(value.length - 1)
          } else return value;
          // 姓名脱敏：保留姓氏，名字部分用*替代
        case 'name':
          if (value.length <= 1) {
            return value;
          } else if (value.length === 2) {
            return value.charAt(0) + '*';
          } else {
            const firstName = value.charAt(0);
            const lastName = value.charAt(value.length - 1);
            return firstName + '*'.repeat(value.length - 2) + lastName;
          }
        default:
          // 自动识别数据类型并应用相应的脱敏规则
          // 身份证号识别（18位数字）
          if (/^\d{18}$/.test(value)) {
            return this.desensitizeTextFn(value, 'idCard');
          }
          // 手机号识别（11位数字）
          else if (/^1\d{10}$/.test(value)) {
            return this.desensitizeTextFn(value, 'phone');
          }
          // 姓名识别（2-4个中文字符）
          else if (/^[\u4e00-\u9fa5]{2,4}$/.test(value)) {
            return this.desensitizeTextFn(value, 'name');
          }
          // 其他情况使用通用脱敏规则
          else {
            if (value.length <= 2) {
              // 长度小于等于2，全部显示为**
              return '**';
            } else if (value.length <= 5) {
              // 长度3-5，保留首尾字符
              return value.charAt(0) + '*'.repeat(value.length - 2) + value.charAt(value.length - 1);
            } else {
              // 长度大于5，保留前2位和后2位
              return value.substring(0, 2) + '*'.repeat(value.length - 4) + value.substring(value.length - 2);
            }
          }
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.text-desensitize-container {
  .text-box {
    display: inline-block;
    vertical-align: middle;
  }

  .icon-box {
    display: inline-block;
    vertical-align: middle;
    width: 20px;
    margin-top: 3px;
    margin-left: 10px;
    font-weight: bold;
    fill: #333;
    cursor: pointer;

    img {
      width: 20px;
      height: 20px;
    }
  }
}

.input-container {
  position: relative;
}

.transparent-input {
  ::v-deep .el-input__inner {
    color: transparent;
    text-shadow: 0 0 0 #666; /* 保留文字占位空间 */
  }
}

.icon-box {
  cursor: pointer;
  display: flex;
  align-items: center;
  height: 100%;
  padding-right: 8px;
}
</style>
